After discussing the issue with our developers, we came to the conclusion: essentially, the R2018b behavior was a bug. R2019a fixed the issue.
With the keyword "static", tunable parameters are declared as static class members. A static member has only one memory location for any number of instances for the class. So, the R2019a behavior is the intended behavior.
In general, parameters defined by workspace variables are shared across all instances of models / code, and Model Default for Simulink.Parameter should result in a shared parameter.
There is no way to generate instance-specific parameters for top model C++ code generation in R2019a. However, our developers would like to add support for instance-specific parameters for top model code generation in a future release.