If 3y works, it only works accidentally and it might change in future.
Zeroing gradient is different with retaining the graph. It makes sense to not retaining by default:

after each forward, it is common to use grad values to update the parameters. then your x should change, and calculating gradient through y is incorrect now because y is computed using old x.
to save memory

Do not think of x and y as symbolic variables. Think of them as tensors with values.
What I don’t understand is that why you don’t like retain_graph + zero_grad. It is the perfectly reasonable thing to do.