I do not understand the need for the line
F = torch.stack(Variable(torch.from_numpy(X).type(dtype), requires_grad=True))

If I understand your code correctly, X = model output, so it must be a Variable already. So when you rewrap it in a Variable you cut off the gradient flow. Besides if you give only one argument to torch.stack then it passes that argument through untouched.
If you replace the above line with
F = X

then the contents of F will be as before, but the gradient flow will no longer be cut off.