My best guess would be that model.eval() might have been forgotten in the evaluation code, which would update the running stats of all batchnorm layers with the test set and would thus leak the data.
The current code snippet calls model.eval() during the last iteration of the training, but I would recommend to add it to the validation function explicitly in case it was reset somewhere else to training mode.
Let me know, if that doesn’t help.