The only ways I can really think about doing this are hacks. For instance using marginal Interpolated distributions to “freeze” the posterior distribution:
https://docs.pymc.io/notebooks/updating_priors.html
or, duplicating the “new” data several times, and pairing each copy with a random sample from the fixed effect posterior.
Another possibility would be to add a Freeze() transformation (Transformations of a random variable from one space to another. — PyMC3 3.10.0 documentation) that sets the Jacobian to 0 preventing variable updates. (Or infinity so the inverse Jacobian is zero – you get the idea.) Then you could have something like
a_train = pm.Deterministic('a_i_tr', a_0 + train_offset/precision_a ** .5)
a_test = pm.Deterministic('a_i_te', Freeze(a_0) + test_offset/precision_a ** .5)
[...] # use a_train to define y_hat_ij_train; a_test to define y_hat_ij_test
y_tr = pm.Normal('y_train', mu=y_hat_ij_train, tau=precision, observed=train_df['Y'], dims="obs_id")
y_te = pm.Normal('y_test', mu=y_hat_ij_test, tau=precision, observed=test_df['Y'], dims="obs_id")