Relay operators and their (multiple?) implementations

Hello,

I am trying to understand more about Relay operators. More specifically I have been trying to understand how some Relay operators are implemented.

Lets use relay.nn.pad as example.

  1. I can see that it is registered into Relay in pad’s relay registering
  2. The compute rule (AFAIK) leads to pad’s c implementation
  3. There seems to be second implementation in pad’s python implementation
  4. While here we are registering pad’s schedule

So 2. and 3. are confusing me since, as far as I can tell, they implement exactly the same things. I am unsure in which cases either or will be used. Does this duplication of functionality follow some rule/reason?

Now 4. is also not clear, because the decorator indicates a broadcast but actually calls with an _schedule_injective. Is this also expected? if all broadcast schedules are injective, why the difference at this level?

Thank you