Singular. I teach singular and I beg people to use Singular. Not only do we not have to remember if there is or isn't an S if we just know that table names are singular, we also don't have to worry about the problem of "ys" vs "ies" which seems to confound many of our ESL friends and coworkers.
It also makes thing simpler when you're creating or using automation tools- a many to many join table between puppies and foods isn't puppy_foods or puppies_food or puppies_food or foods_puppies or food_puppies or foods_puppy it's just the table names, singular, in alphabetical order: food_puppy, and when a piece of automation finds a table with underscore(s) it can just know that the entities parsed out will exist as tables. If I see food_puppy, I know there is a food table and a puppy table, and I also know that the PK in those table is (a) the first field (b) a unique identifier (c) a rowguid (d) named FoodRecordID and PuppyRecordID. I know the first two fields in the Food_Puppy table are also FoodRecordID and PuppyRecordID.
The best part about the singular naming, from an automation standpoint, is that if my code finds a field that ends in "recordid" then there is guaranteed to be a table named whatever was before the recordid part. I don't have to know that puppyrecordid is in the puppies (or puppys) table. I just chop the recordid and what remains will be a table name, without any other worries. or... should I say... without a further worry. 🙂