Hi,
The reason why this exists is because a non-leaf Variable is a tensor corresponding to a temporary computation between leaf Variables and the final Variable for which you are going to backpropagate. Since these are intermediary computation, it makes no sense to change them with an optimizer as you would end up with an invalid computational graph because you modified some values in the middle of the graph and so calling backward on that graph would return wrong values.
if you want to optimize a given element, it needs to be a leaf Variable. The way you do it is right.
One thing is that you do top(v).backward([v]). What this does is backpropagating from the output of top using the content of v as the initial gradients, is that expected? Also if you’re not doing double backprop, and this is actually the intended behavior, you can speed this up by providing v.detach() to the backward function. Because right now, since v.requires_grad=True, it creates the full graph for the double backward.