Thank you  Your help is pushing me in the right direction. Since I’m planning to use the variable that holds the pre-pooling shape in the decoder, would something like this work instead? :
self.nn_1 = nn.Sequential( ... )
self.pre-pool_shape = x.shape
self.nn_adpative_pool = nn.Sequential(...)
self.nn_2 = nn.Sequential(....)

self.mu & logvar_fc layers

self.decoder_nn = nn.Sequential( ... <using variable pre-pool_shape> ...)

Or if using your first method, the dimensions are stored in shape_before_pooling which is in forward(). How can I use this variable in self.decoder_nn? Right now, my forward, encode and decode looks like:
 def encode(self, x):
        encoded = self.nn_1(x)
        encoded_flat = self.flatten(encoded)
        encoded_flat = self.nn_2(encoded_flat)
        mu = self.mu_fc(encoded_flat)
        logvar = self.logvar_fc(encoded_flat)
        return mu, logvar

    def decode(self, z):
        z_4d = self.restore_dim(z)
        return self.decoder_nn(z_4d)

    def forward(self, x):
        mu,logvar = self.encode(x)
        z = self.reparametrize(mu, logvar)
        decoded = self.decode(z)
        return (decoded, z, mu, logvar)

If I make the variable within forward() as you have, create a new parameter in decode() as such: decode(self, z, prePoolShape), and inside that function, do return self.decoder_nn(z_4d, prePoolShape), would that work?
Sorry if this seems really beginner. I haven’t had too much experience with VAEs and neural networks in general, and again I really appreciate your help