Hi,
If you want to ignore a bunch of ops when the gradient is computed, you can wrap them into a no_grad block:
with torch.no_grad():
    latent_reconstruct = encoder(y)

Another way to do this is to explicitly break the graph so that the y used in the second encoding is not linked to the rest of the network:
latent_reconstruct = encoder(y.detach())

Both should work fine. You can choose the one that fits best in your code.