crop bounding boxes
### Issue type

Feature Request

### Have you reproduced the bug with TensorFlow Nightly?

Yes

### Source

source

### TensorFlow version

2.12.0

### Custom code

Yes

### OS platform and distribution

Linux

### Mobile device

_No response_

### Python version

_No response_

### Bazel version

_No response_

### GCC/compiler version

_No response_

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current behaviour?

I think that TF may be missing a **utility to crop several bounding boxes**. It should be **vectorized for better performance**, as cropping one-by-one is known to be slow. I have not found it in API (but maybe is out there?).

The use case is clear – extracting patches of annotated images for object detection.

The util function should take a tensor of boxes `(n_boxes,4)` and a window/patch `(4,)` and crop all the boxes to a given window. Note that we want to **crop boxes, not an image**.

So, starting from this:
![image](https://github.com/tensorflow/tensorflow/assets/31315784/1224a91d-325a-4f9f-bd45-f248be8715ce)

We want to achieve this:
![image](https://github.com/tensorflow/tensorflow/assets/31315784/94e3596c-2f94-45ee-bddf-1c84725a1da3)


In terms of other implementations, this one from MatLab: https://www.mathworks.com/help/vision/ref/bboxcrop.html

### Standalone code to reproduce the issue

```shell
Here is a proposal, essentially used to generate the image above, what is important that the code is vectorized. 


def crop_bounding_boxes(boxes,window):
    """Crop bounding boxes to the speficied window. 

    Args:
        boxes: A tensor of shape `[n_boxes,4]` describing bounding boxes. Each box is in pixel units and in the format `x_min,y_min,x_max,y_max`
        window A tensor of shape `[4]` describing the window. The window is in pixel units and in the format `x_min,y_min,x_max,y_max`

    Returns:
        _type_: _description_
    """    
    """
    Args:
        boxes 
    The annotation boxes are assumed to be in pixels and in the format `x_min,y_min,x_max,y_max`.

    """
    # assume boxes and patch are given as (x1,y1,x2,y2)

    # compute intersections of rectangles
    tf_ops = [tf.maximum,tf.maximum,tf.minimum,tf.minimum]
    cropped_boxes = [op(window[pos],boxes[:,pos]) for (pos,op) in enumerate(tf_ops)]
    cropped_boxes = tf.stack(cropped_boxes,axis=-1)
    mask = tf.logical_and( tf.less(cropped_boxes[:,0],cropped_boxes[:,2]), tf.less(cropped_boxes[:,1],cropped_boxes[:,3]) )
    cropped_boxes = tf.boolean_mask(cropped_boxes,mask)
    # move the coordinates origin to (x1,y1)
    corner = tf.concat([window[:2],window[:2]],axis=0)
    corner = tf.broadcast_to(corner, cropped_boxes.shape)
    cropped_boxes = cropped_boxes - corner
    return cropped_boxes


See also this [SO discussion](https://stackoverflow.com/questions/59722712/crop-multiple-bounding-boxes-from-image-with-list-of-bounding-boxes/77358447#77358447) and this [Kaggle notebook](https://www.kaggle.com/code/mskorski/efficient-bounding-boxes-cropping/)
```


### Relevant log output

_No response_