docs: def gaussian_bags_of_words(Y, vocab=vocab1k, sigma=1, bag_size=[25, 50], **kwargs):
      """
      Generate Gaussian bags of words based on label assignments
  
      Args:
          Y: np.array of true labels
          sigma: (float) the standard deviation of the Gaussian distributions
          bag_size: (list) the min and max length of bags of words
  
      Returns:
          X: (Tensor) a tensor of indices representing tokens
          D: (list) a list of sentences (strings)
  
      The sentences are conditionally independent, given a label.
      Note that technically we use a half-normal distribution here because we
          take the absolute value of the normal distribution.
  
      Example:
          TBD
  
      """
  
      def make_distribution(sigma, num_words):
          p = abs(np.random.normal(0, sigma, num_words))
          return p / sum(p)
  
      num_words = len(vocab)
      word_dists = {y: make_distribution(sigma, num_words) for y in set(Y)}
      bag_sizes = np.random.choice(range(min(bag_size), max(bag_size)), len(Y))
  
      X = []
      items = []
      for i, (y, length) in enumerate(zip(Y, bag_sizes)):
          x = torch.from_numpy(np.random.choice(num_words, length, p=word_dists[y]))
          X.append(x)
          items.append(" ".join(vocab[j] for j in x))
  
      return X, items