docs: def extract_patches(images, patch_shape, samples_per_image=40, seed=0,
                      cycle=True):
      """
      Takes a set of images and yields randomly chosen patches of specified size.
  
      Parameters
      ----------
      images : iterable
          The images have to be iterable, and each element must be a Numpy array
          with at least two spatial 2 dimensions as the first and second axis.
      patch_shape : tuple, length 2
          The spatial shape of the patches that should be extracted. If the
          images have further dimensions beyond the spatial, the patches will
          copy these too.
      samples_per_image : int
          Samples to extract before moving on to the next image.
      seed : int
          Seed with which to select the patches.
      cycle : bool
          If True, then the function will produce patches indefinitely, by going
          back to the first image when all are done. If False, the iteration will
          stop when there are no more images.
  
      Returns
      -------
      patch_generator
          This function returns a generator that will produce patches.
  
      Examples
      --------
      >>> import deepdish as dd
      >>> import matplotlib.pylab as plt
      >>> import itertools
      >>> images = ag.io.load_example('mnist')
  
      Now, let us say we want to exact patches from the these, where each patch
      has at least some activity.
  
      >>> gen = dd.image.extract_patches(images, (5, 5))
      >>> gen = (x for x in gen if x.mean() > 0.1)
      >>> patches = np.array(list(itertools.islice(gen, 25)))
      >>> patches.shape
      (25, 5, 5)
      >>> dd.plot.images(patches)
      >>> plt.show()
  
      """
      rs = np.random.RandomState(seed)
      for Xi in itr.cycle(images):
          # How many patches could we extract?
          w, h = [Xi.shape[i]-patch_shape[i] for i in range(2)]
  
          assert w > 0 and h > 0
  
          # Maybe shuffle an iterator of the indices?
          indices = np.asarray(list(itr.product(range(w), range(h))))
          rs.shuffle(indices)
          for x, y in indices[:samples_per_image]:
              yield Xi[x:x+patch_shape[0], y:y+patch_shape[1]]