To add to @Yaroslav_Bulatov 's great explanation, the PyTorch derivatives are defined in derivatives.yaml. This is what you see in t.grad_fn for tensors computed with gradient requriements.
For functions not in there, the story is a bit more elaborate: these run under autograd and PyTorch records the operations, just like it does for your code. For example einsum will is implemented by calling permute, reshape, and bmm, so these are what you’ll see when looking at .grad_fn or traversing the graph there (by using .grad_fn.next_functions etc. appropriately).
Best regards
Thomas