We had some relevant discussion on this here:
What happened to the UnloadTexture() functions? - Other Courses / Ask - GameDev.tv
Ultimately, since the same texture may even be shared among multiple entities, calling UnloadTexture prematurely (such as in a destructor) could be problematic. So if you’re going to do it, and there are arguments for/against whether you absolutely should always do it, would be as part of the application cleanup at specific points.
For example, a texture-heavy program with different graphical requirements between levels/scenes, it may make sense to manage the loading and unloading of the textures as part of the level loading, so as to not load too much in one go from the start or leaving it in memory forever when it would end up being a burden.
Otherwise, when the program ends, the memory will be freed anyway whether you explicitly call it or not. It’s not hanging on to file handles or anything in RayLib once the texture is loaded into memory, so you don’t have to worry about freeing up those resources gracefully.