z.grad always matches the shape of z so that each element of z.grad is the gradient with respect to the corresponding element of z.
This makes it easy to apply updates to z. Optimizers all do something like this
p.data += -learning_rate * p.grad.data

I haven’t thought through the implications of the chain rule, but if you want to do this
myvar.backward(grads)

then grads should have the same shape as myvar.
When myvar has only one element and if you omit grads pytorch assumes that you meant to pass in Variable(torch.ones(myvar.size()))