text: Title: Using TFP distributions directly in `sample` primitive
  Body: Quoted from [the forum](https://forum.pyro.ai/t/sample-from-the-mixture-same-family-distribution/3178/6): The current wrappers in `numpyro.contrib.tfp` seems to not work for special distributions like MixtureSameFamily. For now, to make it work, we'll need to do
  ```python
  from numpyro.contrib.tfp.distributions import TFPDistribution
  import tensorflow_probability...distributions as tfd
  
  def model():
      x = sample("x", TFPDistribution(tfd.MixtureSampleFamily(...)))
  ```
  In the long term, I think it would be nice to use TFP distributions directly in the `sample` primitive:
  ```python
  import tensorflow_probability...distributions as tfd
  
  def model():
      x = sample("x", tfd.MixtureSampleFamily(...))
  ```
  
  I believe it is enough to modify [`sample` primitive](https://github.com/pyro-ppl/numpyro/blob/e55f0d41c9eba48a10e88fb403a5e016f18857e6/numpyro/primitives.py#L104) such that if `fn` is not a NumPyro distribution, we will check if `tensorflow_probability` is available, then trying to check if `fn` is a TFP distribution. If yes, then we replace `fn` by `numpyro.contrib.tfp.distributions.TFPDistribution[type(fn)](**fn.parameters)` or by
  ```python
  new_fn = TFPDistribution()
  new_fn.tfp_dist = fn
  new_fn.tfd_class = type(fn)  # and extra repr if needed
  ```