My guess is that the problem is that what Keras means by “same” padding is different than what you might expect. I have only checked this out in the “forward convolution” case, but I’ll bet the same rule applies in the transposed convolution case as well. What they do is compute the padding for “same” with the stride hard-coded to 1. That means you only actually get the same size as the output if the stride actually is 1. In the case of stride > 1, the output will not be the same size. If you think this is a clear violation of the Principle of Least Astonishment, I wouldn’t disagree with you. Which part of “same” don’t they understand? Why they do it that way, I have no idea, but that’s the way it works. Try it and see!
I have been meaning to get back to this and actually construct some experiments that demonstrate this, but have not had time. Maybe this will motivate me to get that done sooner rather than later. But if you have time to try that, please show us what you learn! If you can show that what I said above is wrong, that would be a big relief!
Update January 2023: it turns out there is a good reason why “same” padding is only calculated with stride = 1. If you actually solve for the amount of padding required to get the same sized output when stride is 2 or greater, the numbers are crazy. Here’s a more recent thread that shows some examples of what would be required.